#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
NSA5312 上位机主窗口
Main Window for NSA5312 Upper Computer Software

功能特性：
- 串口连接管理
- 设备控制面板
- 数据采集与显示
- 自定义命令测试
- 日志记录与保存
- 校准功能
"""

import sys
import json
import os
from datetime import datetime
from typing import Dict, List, Optional

from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                           QHBoxLayout, QTabWidget, QLabel, QLineEdit, QPushButton,
                           QComboBox, QTextEdit, QTableWidget, QTableWidgetItem,
                           QGroupBox, QGridLayout, QSpinBox, QDoubleSpinBox,
                           QCheckBox, QProgressBar, QStatusBar, QMenuBar, QAction,
                           QFileDialog, QMessageBox, QSplitter, QFrame)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer, QSettings
from PyQt5.QtGui import QFont, QColor, QPalette, QIcon

from serial_handler import SerialHandler, SerialConfig, ConnectionState, NSA5312CommandHelper
from serial_protocol import NSA5312Protocol, CommandCode, StatusCode
from data_logger import DataLogger
from calibration_widget import CalibrationWidget
from custom_command_widget import CustomCommandWidget
from comprehensive_test_widget import ComprehensiveTestWidget
from communication_test_widget import CommunicationTestWidget
from adc_collection_widget import ADCCollectionWidget
from device_one_test_widget import OneTestWidget

class ConnectionWidget(QWidget):
    """串口连接控件"""
    
    connection_changed = pyqtSignal(bool)
    
    def __init__(self, serial_handler: SerialHandler):
        super().__init__()
        self.serial_handler = serial_handler
        self.init_ui()
        
        # 设置回调
        self.serial_handler.set_callbacks(
            state_callback=self.on_connection_state_changed
        )
        
        # 定时器用于刷新端口列表
        self.port_refresh_timer = QTimer()
        self.port_refresh_timer.timeout.connect(self.refresh_ports)
        self.port_refresh_timer.start(2000)  # 每2秒刷新一次
    
    def init_ui(self):
        """初始化UI"""
        layout = QHBoxLayout()
        
        # 串口选择
        layout.addWidget(QLabel("串口:"))
        self.port_combo = QComboBox()
        self.port_combo.setMinimumWidth(100)
        layout.addWidget(self.port_combo)
        
        # 波特率选择
        layout.addWidget(QLabel("波特率:"))
        self.baudrate_combo = QComboBox()
        self.baudrate_combo.addItems(['9600', '19200', '38400', '57600', '115200'])
        self.baudrate_combo.setCurrentText('9600')
        layout.addWidget(self.baudrate_combo)
        
        # 连接按钮
        self.connect_btn = QPushButton("连接")
        self.connect_btn.clicked.connect(self.toggle_connection)
        layout.addWidget(self.connect_btn)
        
        # 状态指示器
        self.status_label = QLabel("未连接")
        self.status_label.setStyleSheet("color: red; font-weight: bold;")
        layout.addWidget(self.status_label)
        
        # 刷新按钮
        refresh_btn = QPushButton("刷新")
        refresh_btn.clicked.connect(self.refresh_ports)
        layout.addWidget(refresh_btn)
        
        layout.addStretch()
        self.setLayout(layout)
        
        # 初始化端口列表
        self.refresh_ports()
    
    def refresh_ports(self):
        """刷新端口列表"""
        current_port = self.port_combo.currentText()
        self.port_combo.clear()
        
        ports = self.serial_handler.get_available_ports()
        self.port_combo.addItems(ports)
        
        # 恢复之前选择的端口
        if current_port and current_port in ports:
            self.port_combo.setCurrentText(current_port)
    
    def toggle_connection(self):
        """切换连接状态"""
        if self.serial_handler.is_connected():
            self.serial_handler.disconnect()
        else:
            port = self.port_combo.currentText()
            baudrate = int(self.baudrate_combo.currentText())
            
            if not port:
                QMessageBox.warning(self, "错误", "请选择串口")
                return
            
            config = SerialConfig(
                port=port,
                baudrate=baudrate
            )
            
            self.serial_handler.set_config(config)
            self.serial_handler.connect()
    
    def on_connection_state_changed(self, state: ConnectionState):
        """连接状态变化回调"""
        if state == ConnectionState.CONNECTED:
            self.status_label.setText("已连接")
            self.status_label.setStyleSheet("color: green; font-weight: bold;")
            self.connect_btn.setText("断开")
            self.connection_changed.emit(True)
        elif state == ConnectionState.CONNECTING:
            self.status_label.setText("连接中...")
            self.status_label.setStyleSheet("color: orange; font-weight: bold;")
        else:
            self.status_label.setText("未连接")
            self.status_label.setStyleSheet("color: red; font-weight: bold;")
            self.connect_btn.setText("连接")
            self.connection_changed.emit(False)
            
            if state == ConnectionState.ERROR:
                error_msg = self.serial_handler.get_last_error()
                QMessageBox.critical(self, "连接错误", f"串口连接失败：{error_msg}")

class DeviceControlWidget(QWidget):
    """设备控制面板"""
    
    def __init__(self, command_helper: NSA5312CommandHelper):
        super().__init__()
        self.command_helper = command_helper
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        layout = QVBoxLayout()
        
        # 设备信息组
        info_group = QGroupBox("设备信息")
        info_layout = QGridLayout()
        
        # 版本信息
        info_layout.addWidget(QLabel("固件版本:"), 0, 0)
        self.version_label = QLabel("未知")
        info_layout.addWidget(self.version_label, 0, 1)
        
        # 获取版本按钮
        get_version_btn = QPushButton("获取版本")
        get_version_btn.clicked.connect(self.get_version)
        info_layout.addWidget(get_version_btn, 0, 2)
        
        info_group.setLayout(info_layout)
        layout.addWidget(info_group)
        
        # GPIO控制组
        gpio_group = QGroupBox("GPIO控制")
        gpio_layout = QGridLayout()
        
        # 行控制
        gpio_layout.addWidget(QLabel("行控制:"), 0, 0)
        self.row_channel_spin = QSpinBox()
        self.row_channel_spin.setRange(0, 63)
        gpio_layout.addWidget(self.row_channel_spin, 0, 1)
        
        
        row_btn = QPushButton("设置行")
        row_btn.clicked.connect(self.set_row_control)
        gpio_layout.addWidget(row_btn, 0, 2)
        
        # 列控制
        gpio_layout.addWidget(QLabel("列控制:"), 1, 0)
        self.col_channel_spin = QSpinBox()
        self.col_channel_spin.setRange(0, 63)
        gpio_layout.addWidget(self.col_channel_spin, 1, 1)
        
        
        col_btn = QPushButton("设置列")
        col_btn.clicked.connect(self.set_col_control)
        gpio_layout.addWidget(col_btn, 1, 2)
        
        gpio_group.setLayout(gpio_layout)
        layout.addWidget(gpio_group)
        
        # ADC读取组
        adc_group = QGroupBox("ADC采集")
        adc_layout = QGridLayout()
        
        # 单通道读取
        adc_layout.addWidget(QLabel("通道:"), 0, 0)
        self.adc_channel_spin = QSpinBox()
        self.adc_channel_spin.setRange(0, 63)
        adc_layout.addWidget(self.adc_channel_spin, 0, 1)
        
        read_adc_btn = QPushButton("读取ADC")
        read_adc_btn.clicked.connect(self.read_adc)
        adc_layout.addWidget(read_adc_btn, 0, 2)
        
        self.adc_value_label = QLabel("0")
        adc_layout.addWidget(self.adc_value_label, 0, 3)
        
        # 64通道采集
        collect_64ch_btn = QPushButton("采集64通道")
        collect_64ch_btn.clicked.connect(self.collect_64ch)
        adc_layout.addWidget(collect_64ch_btn, 1, 0, 1, 2)
        
        # 进度条
        self.progress_bar = QProgressBar()
        adc_layout.addWidget(self.progress_bar, 1, 2, 1, 2)
        
        adc_group.setLayout(adc_layout)
        layout.addWidget(adc_group)
        
        # 接口测试组
        interface_group = QGroupBox("接口测试")
        interface_layout = QGridLayout()
        
        # I2C测试
        interface_layout.addWidget(QLabel("I2C设备地址:"), 0, 0)
        self.i2c_addr_spin = QSpinBox()
        self.i2c_addr_spin.setRange(0, 127)
        self.i2c_addr_spin.setValue(0x50)
        interface_layout.addWidget(self.i2c_addr_spin, 0, 1)
        
        interface_layout.addWidget(QLabel("寄存器地址:"), 0, 2)
        self.i2c_reg_spin = QSpinBox()
        self.i2c_reg_spin.setRange(0, 255)
        interface_layout.addWidget(self.i2c_reg_spin, 0, 3)
        
        i2c_read_btn = QPushButton("I2C读取")
        i2c_read_btn.clicked.connect(self.i2c_read)
        interface_layout.addWidget(i2c_read_btn, 0, 4)
        
        # SPI测试
        spi_test_btn = QPushButton("SPI测试")
        spi_test_btn.clicked.connect(self.spi_test)
        interface_layout.addWidget(spi_test_btn, 1, 0)
        
        # OWI测试
        owi_test_btn = QPushButton("OWI测试")
        owi_test_btn.clicked.connect(self.owi_test)
        interface_layout.addWidget(owi_test_btn, 1, 1)
        
        interface_group.setLayout(interface_layout)
        layout.addWidget(interface_group)
        
        layout.addStretch()
        self.setLayout(layout)
    
    def get_version(self):
        """获取版本信息"""
        try:
            response = self.command_helper.get_version()
            if response.success:
                version = response.data[0] if response.data else 0
                self.version_label.setText(str(version))
            else:
                QMessageBox.warning(self, "错误", f"获取版本失败: {response.error_msg}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"获取版本异常: {str(e)}")
    
    def set_row_control(self):
        """设置行控制"""
        try:
            channel = self.row_channel_spin.value()
            response = self.command_helper.control_gpio_row(channel)
            
            if not response.success:
                QMessageBox.warning(self, "错误", f"设置行控制失败: {response.error_msg}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"设置行控制异常: {str(e)}")
    
    def set_col_control(self):
        """设置列控制"""
        try:
            channel = self.col_channel_spin.value()
            response = self.command_helper.control_gpio_col(channel)
            
            if not response.success:
                QMessageBox.warning(self, "错误", f"设置列控制失败: {response.error_msg}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"设置列控制异常: {str(e)}")
    
    def read_adc(self):
        """读取ADC值"""
        try:
            channel = self.adc_channel_spin.value()
            response = self.command_helper.read_adc_channel(channel)
            
            if response.success and response.data:
                adc_value = int.from_bytes(response.data[:2], byteorder='big')
                self.adc_value_label.setText(str(adc_value))
            else:
                QMessageBox.warning(self, "错误", f"读取ADC失败: {response.error_msg}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"读取ADC异常: {str(e)}")
    
    def collect_64ch(self):
        """采集64通道数据"""
        try:
            self.progress_bar.setValue(0)
            
            response = self.command_helper.collect_64ch_data(CommandCode.ADC_64CH_COLLECT)
            
            if response.success:
                self.progress_bar.setValue(100)
                QMessageBox.information(self, "成功", "64通道数据采集完成")
            else:
                QMessageBox.warning(self, "错误", f"64通道采集失败: {response.error_msg}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"64通道采集异常: {str(e)}")
    
    def i2c_read(self):
        """I2C读取测试"""
        try:
            device_addr = self.i2c_addr_spin.value()
            reg_addr = self.i2c_reg_spin.value()
            
            response = self.command_helper.i2c_read(device_addr, reg_addr, 1)
            
            if response.success:
                data_str = " ".join(f"{b:02X}" for b in response.data)
                QMessageBox.information(self, "I2C读取成功", f"数据: {data_str}")
            else:
                QMessageBox.warning(self, "错误", f"I2C读取失败: {response.error_msg}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"I2C读取异常: {str(e)}")
    
    def spi_test(self):
        """SPI测试"""
        try:
            test_data = b'\x55\xAA'
            response = self.command_helper.spi_write(test_data)
            
            if response.success:
                QMessageBox.information(self, "SPI测试成功", "SPI写入操作完成")
            else:
                QMessageBox.warning(self, "错误", f"SPI测试失败: {response.error_msg}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"SPI测试异常: {str(e)}")
    
    def owi_test(self):
        """OWI测试"""
        try:
            test_data = b'\x00\x01\x02'
            response = self.command_helper.owi_write(test_data)
            
            if response.success:
                QMessageBox.information(self, "OWI测试成功", "OWI写入操作完成")
            else:
                QMessageBox.warning(self, "错误", f"OWI测试失败: {response.error_msg}")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"OWI测试异常: {str(e)}")

class DataDisplayWidget(QWidget):
    """数据显示控件"""
    
    def __init__(self):
        super().__init__()
        self.init_ui()
    
    def init_ui(self):
        """初始化UI"""
        layout = QVBoxLayout()
        
        # 数据表格
        self.data_table = QTableWidget()
        self.data_table.setColumnCount(4)
        self.data_table.setHorizontalHeaderLabels(["通道", "原始值", "校准值", "温度"])
        layout.addWidget(self.data_table)
        
        # 控制按钮
        button_layout = QHBoxLayout()
        
        clear_btn = QPushButton("清空数据")
        clear_btn.clicked.connect(self.clear_data)
        button_layout.addWidget(clear_btn)
        
        export_btn = QPushButton("导出数据")
        export_btn.clicked.connect(self.export_data)
        button_layout.addWidget(export_btn)
        
        button_layout.addStretch()
        layout.addLayout(button_layout)
        
        self.setLayout(layout)
    
    def update_data(self, channel: int, raw_value: int, calibrated_value: float, temperature: float):
        """更新数据"""
        row = channel
        
        # 确保表格有足够的行
        if row >= self.data_table.rowCount():
            self.data_table.setRowCount(row + 1)
        
        # 更新数据
        self.data_table.setItem(row, 0, QTableWidgetItem(str(channel)))
        self.data_table.setItem(row, 1, QTableWidgetItem(str(raw_value)))
        self.data_table.setItem(row, 2, QTableWidgetItem(f"{calibrated_value:.3f}"))
        self.data_table.setItem(row, 3, QTableWidgetItem(f"{temperature:.1f}°C"))
    
    def clear_data(self):
        """清空数据"""
        self.data_table.setRowCount(0)
    
    def export_data(self):
        """导出数据"""
        filename, _ = QFileDialog.getSaveFileName(
            self, "导出数据", "", "CSV Files (*.csv);;All Files (*)"
        )
        
        if filename:
            try:
                with open(filename, 'w', encoding='utf-8') as f:
                    # 写入表头
                    f.write("通道,原始值,校准值,温度\n")
                    
                    # 写入数据
                    for row in range(self.data_table.rowCount()):
                        data = []
                        for col in range(self.data_table.columnCount()):
                            item = self.data_table.item(row, col)
                            data.append(item.text() if item else "")
                        f.write(",".join(data) + "\n")
                
                QMessageBox.information(self, "成功", f"数据已导出到: {filename}")
            except Exception as e:
                QMessageBox.critical(self, "错误", f"导出数据失败: {str(e)}")

class MainWindow(QMainWindow):
    """主窗口"""
    
    def __init__(self):
        super().__init__()
        self.settings = QSettings("NSA5312", "UpperComputer")
        
        # 初始化组件
        self.serial_handler = SerialHandler(log_callback=self.log_message)
        self.command_helper = NSA5312CommandHelper(self.serial_handler)
        self.data_logger = DataLogger()
        
        self.init_ui()
        self.load_settings()
    
    def init_ui(self):
        """初始化UI"""
        self.setWindowTitle("NSA5312 上位机软件 v1.0")
        self.setGeometry(100, 100, 1200, 800)
        
        # 创建菜单栏
        self.create_menu_bar()
        
        # 创建状态栏
        self.statusBar().showMessage("就绪")
        
        # 创建中央控件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 主布局
        main_layout = QVBoxLayout(central_widget)
        
        # 连接控件
        self.connection_widget = ConnectionWidget(self.serial_handler)
        self.connection_widget.connection_changed.connect(self.on_connection_changed)
        main_layout.addWidget(self.connection_widget)
        
        # 创建分割器
        splitter = QSplitter(Qt.Horizontal)
        
        # 创建选项卡
        self.tab_widget = QTabWidget()


        
        # 设备控制选项卡
        self.device_control_widget = DeviceControlWidget(self.command_helper)
        self.tab_widget.addTab(self.device_control_widget, "设备控制")

        # 单颗测试选项卡
        self.device_one_widget = OneTestWidget(self.command_helper)
        self.tab_widget.addTab(self.device_one_widget,"单颗测试")
        
        # 数据显示选项卡
        self.data_display_widget = DataDisplayWidget()
        self.tab_widget.addTab(self.data_display_widget, "数据显示")
        
        # 自定义命令选项卡
        self.custom_command_widget = CustomCommandWidget(self.command_helper)
        self.tab_widget.addTab(self.custom_command_widget, "自定义命令")
        
        # 校准选项卡
        self.calibration_widget = CalibrationWidget(self.command_helper)
        self.tab_widget.addTab(self.calibration_widget, "校准功能")
        
        # 综合测试选项卡
        self.comprehensive_test_widget = ComprehensiveTestWidget(self.command_helper)
        self.tab_widget.addTab(self.comprehensive_test_widget, "综合测试")
        
        # 通信测试选项卡
        self.communication_test_widget = CommunicationTestWidget(self.command_helper)
        self.tab_widget.addTab(self.communication_test_widget, "通信测试")
        
        # ADC数据采集选项卡
        self.adc_collection_widget = ADCCollectionWidget(self.command_helper)
        self.tab_widget.addTab(self.adc_collection_widget, "ADC采集")
        
        splitter.addWidget(self.tab_widget)
        
        # 日志区域
        log_frame = QFrame()
        log_frame.setFrameStyle(QFrame.StyledPanel)
        log_layout = QVBoxLayout(log_frame)
        
        log_layout.addWidget(QLabel("日志信息:"))
        # log_layout.setSizeConstraint()
        self.log_text = QTextEdit()
        
        self.log_text.setFont(QFont("Courier", 9))
        log_layout.addWidget(self.log_text)
        
        # 日志控制按钮
        log_button_layout = QHBoxLayout()
        
        clear_log_btn = QPushButton("清空日志")
        clear_log_btn.clicked.connect(self.clear_log)
        log_button_layout.addWidget(clear_log_btn)
        
        save_log_btn = QPushButton("保存日志")
        save_log_btn.clicked.connect(self.save_log)
        log_button_layout.addWidget(save_log_btn)
        
        log_button_layout.addStretch()
        log_layout.addLayout(log_button_layout)
        
        splitter.addWidget(log_frame)
        
        # 设置分割器比例
        splitter.setSizes([800, 400])
        
        main_layout.addWidget(splitter)
        
        # 初始状态
        self.on_connection_changed(False)
    
    def create_menu_bar(self):
        """创建菜单栏"""
        menubar = self.menuBar()
        
        # 文件菜单
        file_menu = menubar.addMenu('文件')
        
        save_config_action = QAction('保存配置', self)
        save_config_action.triggered.connect(self.save_config)
        file_menu.addAction(save_config_action)
        
        load_config_action = QAction('加载配置', self)
        load_config_action.triggered.connect(self.load_config)
        file_menu.addAction(load_config_action)
        
        file_menu.addSeparator()
        
        exit_action = QAction('退出', self)
        exit_action.triggered.connect(self.close)
        file_menu.addAction(exit_action)
        
        # 工具菜单
        tools_menu = menubar.addMenu('工具')
        
        # 帮助菜单
        help_menu = menubar.addMenu('帮助')
        
        about_action = QAction('关于', self)
        about_action.triggered.connect(self.show_about)
        help_menu.addAction(about_action)
    
    def log_message(self, message: str):
        """记录日志消息"""
        timestamp = datetime.now().strftime("%H:%M:%S")
        formatted_message = f"[{timestamp}] {message}"
        self.log_text.append(formatted_message)
        
        # 自动滚动到底部
        cursor = self.log_text.textCursor()
        cursor.movePosition(cursor.End)
        self.log_text.setTextCursor(cursor)
        
        # 记录到文件
        self.data_logger.log_message(formatted_message)
    
    def clear_log(self):
        """清空日志"""
        self.log_text.clear()
    
    def save_log(self):
        """保存日志"""
        filename, _ = QFileDialog.getSaveFileName(
            self, "保存日志", "", "Text Files (*.txt);;All Files (*)"
        )
        
        if filename:
            try:
                with open(filename, 'w', encoding='utf-8') as f:
                    f.write(self.log_text.toPlainText())
                QMessageBox.information(self, "成功", f"日志已保存到: {filename}")
            except Exception as e:
                QMessageBox.critical(self, "错误", f"保存日志失败: {str(e)}")
    
    def on_connection_changed(self, connected: bool):
        """连接状态变化处理"""
        self.tab_widget.setEnabled(connected)
        
        if connected:
            self.statusBar().showMessage("设备已连接")
            self.log_message("设备连接成功")
        else:
            self.statusBar().showMessage("设备未连接")
            self.log_message("设备连接断开")
    
    def save_config(self):
        """保存配置"""
        filename, _ = QFileDialog.getSaveFileName(
            self, "保存配置", "", "JSON Files (*.json);;All Files (*)"
        )
        
        if filename:
            try:
                config = {
                    "serial_port": self.connection_widget.port_combo.currentText(),
                    "baudrate": self.connection_widget.baudrate_combo.currentText(),
                    "window_geometry": [self.x(), self.y(), self.width(), self.height()],
                    "calibration_data": self.calibration_widget.export_config()
                }
                
                with open(filename, 'w', encoding='utf-8') as f:
                    json.dump(config, f, indent=2, ensure_ascii=False)
                
                QMessageBox.information(self, "成功", f"配置已保存到: {filename}")
            except Exception as e:
                QMessageBox.critical(self, "错误", f"保存配置失败: {str(e)}")
    
    def load_config(self):
        """加载配置"""
        filename, _ = QFileDialog.getOpenFileName(
            self, "加载配置", "", "JSON Files (*.json);;All Files (*)"
        )
        
        if filename:
            try:
                with open(filename, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                
                # 恢复串口配置
                if "serial_port" in config:
                    self.connection_widget.port_combo.setCurrentText(config["serial_port"])
                
                if "baudrate" in config:
                    self.connection_widget.baudrate_combo.setCurrentText(config["baudrate"])
                
                # 恢复窗口位置
                if "window_geometry" in config:
                    x, y, w, h = config["window_geometry"]
                    self.setGeometry(x, y, w, h)
                
                # 恢复校准数据
                if "calibration_data" in config:
                    self.calibration_widget.import_config(config["calibration_data"])
                
                QMessageBox.information(self, "成功", f"配置已从 {filename} 加载")
            except Exception as e:
                QMessageBox.critical(self, "错误", f"加载配置失败: {str(e)}")
    
    def load_settings(self):
        """加载设置"""
        # 恢复窗口位置和大小
        if self.settings.contains("geometry"):
            self.restoreGeometry(self.settings.value("geometry"))
        
        # 恢复串口设置
        if self.settings.contains("serial_port"):
            self.connection_widget.port_combo.setCurrentText(
                self.settings.value("serial_port")
            )
        
        if self.settings.contains("baudrate"):
            self.connection_widget.baudrate_combo.setCurrentText(
                self.settings.value("baudrate")
            )
    
    def save_settings(self):
        """保存设置"""
        self.settings.setValue("geometry", self.saveGeometry())
        self.settings.setValue("serial_port", self.connection_widget.port_combo.currentText())
        self.settings.setValue("baudrate", self.connection_widget.baudrate_combo.currentText())
    
    def show_about(self):
        """显示关于对话框"""
        about_text = """
        NSA5312 上位机软件 v1.0
        
        功能特性：
        • 串口通信支持9位接收/8位发送
        • 完整的NSA5312协议支持
        • 多线程数据处理
        • 实时数据采集与显示
        • 自定义命令测试
        • 校准功能与数据管理
        • 日志记录与数据保存
        
        支持协议：
        • 设备地址：0xE1
        • CRC校验：生成多项式0x07
        • 64通道数据采集
        • I2C/SPI/OWI接口控制
        • GPIO控制与ADC采集
        
        开发环境：Python 3.x + PyQt5
        """
        
        QMessageBox.about(self, "关于", about_text)
    
    def closeEvent(self, event):
        """关闭事件处理"""
        # 保存设置
        self.save_settings()
        
        # 断开连接
        if self.serial_handler.is_connected():
            self.serial_handler.disconnect()
        
        event.accept()

def main():
    """主函数"""
    app = QApplication(sys.argv)
    
    # 设置应用程序信息
    app.setApplicationName("NSA5312 Upper Computer")
    app.setApplicationVersion("1.0")
    app.setOrganizationName("NSA5312 Team")
    
    # 创建主窗口
    window = MainWindow()
    window.show()
    
    # 运行应用程序
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()